# encoding: utf-8

from google.appengine.ext import db

# See: http://code.google.com/intl/en/appengine/articles/modeling.html

    
# 录音，专辑，唱片
# TODO -> Album
class Recording(db.Model):
    title = db.StringProperty(required=True)
    
    # 出版/发行年月。
    pub_date = db.DateProperty()
    
    # 演奏者和专辑之间的关系是多对多：
    # 一个演奏者有多个专辑，一个专辑也可能有多个演奏者。
    # 此外，这一多对多关系放在Recording里而不是Musician，原因是：
    # - 一般情况下，人们更习惯说一张专辑由谁演奏，而不是某个演奏者一共演奏了多少专辑。
    # - 一张专辑的演奏者不会太多，但是一个演奏者的专辑就可能很多。所以如果用ListProperty来
    #   表示多对多关系的话，放在Recording里更合适。
    performers = db.ListProperty(db.Key)

    # TODO
    def add_performer(self, p):
        self.performers.append(p.key())
        pass


# 音乐家分为：作曲家，演奏家（或者两者兼而有之）还有乐团。
# 作曲家一般也是演奏家，比如Bach，Mozart等，但是他们都不可能有录音了。
# 作曲家兼演奏家又有录音的，最典型的例子是拉赫玛尼诺夫。
# 所以，到底有没有必要区分这几者呢？
class Musician(db.Model):
    # TODO 分为first name, middle name, last name?
    # TODO 乐团不分first/middle/last name
    # TODO 非中文名字的译名问题。
    name = db.StringProperty(required=False)
    name_full = db.StringProperty(required=False)
    name_tr = db.StringProperty(required=False)
    name_full_tr = db.StringProperty(required=False)
    
    # TODO
    date = db.StringProperty(required=False)
    # 出生年月
    # TODO 对乐团来说，应该是成立时间。
    #birthdate = db.DateProperty(required=False)
    
    country = db.StringProperty(required=False)

    # 时期（古典主义、浪漫主义等等）
    era = db.StringProperty(required=False)
    # 头衔/身份
    # TODO rename
    status = db.StringProperty(required=False)

    # 生平，传记
    # TODO 对乐团来说，应该是介绍（当然，biography也可以）
    biography = db.TextProperty(required=False)

    def display_name(self):
        return "%s %s" % \
            ((self.name or self.name_full), (self.name_tr or self.name_full_tr))

    # 照片（一个音乐家有多张照片）
    @property
    def photos(self):
        return Photo.gql("WHERE musician_uname = :1", self.key().name())
    
    @property
    def recordings(self):
        return Recording.gql("WHERE performers = :1", self.key())


class Photo(db.Model):
    url = db.StringProperty(required=True)
    musician_uname = db.StringProperty(required=True)


# J.S. Bach: Partita for Violin Solo No.2 in D minor, BWV 1004
#  composer         collection        no        key      op
#   1. Allemande
#   2. Corrente
#   3. Sarabande
#   4. Giga
#   5. Ciaccona
#
# Beethoven: Symphony No 9 “Choral”
#   1. Allegro ma non troppo, un poco maestoso
#   2. Molto vivace
#   3. Adagio molto e cantabile
#   4. Presto. Allegro assai
#
# Schubert: Symphony No.9 in C, D.944 - "The Great"
#   composer           
#   1. Andante - Allegro ma non troppo
#   2. Andante con moto
#   3. Scherzo (Allegro vivace)
#   4. Allegro vivace
#
class MultiMovement(db.Model):
    # 作者
    composer = db.ReferenceProperty(Musician)

# J.S. Bach: The 6 Cello Suites
#    schumann    suite:piano              op. 9                Carnaval      狂欢节

# Schubert: Winterreise|冬之旅
#   1. gute nacht 晚安
#   2. die wetterfahne 风信标
#   3. gefrorne tranen 冻结的泪珠
#   ...
#   23. die nebensonnen 幻影的太阳
#   24. der leiermann 街头乐师 
class Suite(db.Model):
    pass
    
# 音乐作品
#    composer        form        key        op        no        name        name_tr    collection
#     mozart    sonata:piano   C major    K. 330      1
#     chopin        mazurka    A minor    op. 17      4

#    schumann

class Translation(db.Model):
    original = db.StringProperty(required=True)
    translated = db.StringProperty(required=False)


class MusicCollection(db.Model):
    # ?
    composer = db.ReferenceProperty(Musician)
    name = db.StringProperty(required=True)


class MusicWork(db.Model):
    # 作者
    composer = db.ReferenceProperty(Musician)
    # 所属曲集
    #collection = db.ReferenceProperty(MusicCollection, required=False)
    # 体裁：交响曲、协奏曲等
    form = db.StringProperty(required=True)
    # 调
    key = db.StringProperty(required=False)
    # 编号
    op = db.StringProperty(required=False)
    no = db.IntegerProperty(required=False)
    
    name = db.StringProperty(required=False)
    
    movements = db.StringListProperty(required=False)

    def display_name(self):
        return ' '.join(filter(lambda x: x,
            [self.name, self.key, self.op, self.no, self.form, self.composer.name]))

    @property
    def movements(self):
        return MusicMovement.gql("WHERE work = :1", self.key())


# 适用于symphony/opera/concerto/suite的子项。
class MusicMovement(db.Model):
    work = db.ReferenceProperty(MusicWork)
    # 序号
    number = db.IntegerProperty(required=True)
    name = db.StringProperty(required=True)

    